<?php

declare(strict_types=1);

namespace App\AdminApi\Module\System\Service;

use App\Common\Model\System\ResourceChunkModel;
use App\Sys;
use Exception;
use League\Flysystem\FilesystemException;
use Zms\Basics\BasicsModel;
use Zms\Basics\BasicsServe;
use Zms\Service\Uploader;
use Zms\Unit\File;

/**
 * 广告服务层
 * Class BannerService
 */
class ResourcesChunkService extends BasicsServe
{

    /**
     * @return ResourceChunkModel::class
     */
    public static function model(): string
    {
        return ResourceChunkModel::class;
    }


    /**
     * 删除大文件上传碎片
     * @param int $limit
     * @return int
     * @throws FilesystemException
     */
    public function clearFileFragment(int $limit = 50): int
    {
        $success = 0;
        $list = $this->search("`time`<?", [time() - 7200])->orderByRaw('id ASC')->limit($limit)->get();
        if (count($list) === 0) {
            return $success;
        }
        $uploader = Sys::container(Uploader::class);
        /**
         * @var ResourceChunkModel $item
         */
        foreach ($list as $item) {
            $uploader->drive('local')->delete($item->path);
            $item->delete();
            $success++;
        }
        return $success;
    }


    /**
     * 记录分片
     * @param string $key
     * @param string $path
     * @param int $index
     * @return bool|BasicsModel
     */
    public function record(string $key, string $path, int $index): bool|BasicsModel
    {
        return $this->created([
            'key' => $key, 'path' => $path, 'index' => $index
        ]);
    }


    /**
     * 合并分片文件,仅限本地上传
     * @param string $key
     * @param int $total
     * @return ?array
     */
    public function mergeChunkFiles(string $key, int $total): ?array
    {
        try {
            $chunk = $this->search(['key' => $key])->orderByRaw('`index` ASC')->get()->toArray();
            if (count($chunk) !== $total) {
                return null;
            }
            $uploader = Sys::container(Uploader::class);
            $filesystem = $uploader->drive('local');
            $path = '';
            foreach ($chunk as $index => $row) {
                if (!$filesystem->has($row['path'])) return null;
                if ($index === 0) {
                    $path = $row['path'];
                } else {
                    $status = File::appendWrite($uploader->getLocalFilePath($path), $filesystem->read($row['path']));
                    if ($status === null) {
                        return null;
                    }
                }
            }
            $newsName = File::changeFileName($path);
            if (rename($uploader->getLocalFilePath($path), $uploader->getLocalFilePath($newsName))) {
                return ['path' => $newsName, 'url' => $uploader->domain() . '/' . trim($newsName, '/')];
            }
            return null;
        } catch (FilesystemException|Exception) {
            return null;
        }
    }
}